﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using PH.Map;
using PH.Common;

namespace Hoshimi.Base
{
     class PathFinder
    {
         public static  bool contieneNodo(List<Nodo> listaCerrada, Nodo aux, Player play) {
             bool esta = false;
             foreach (Nodo nodo in listaCerrada)
             {
                 play.Log.Items.Add("ENTREE");
                 //if ((aux.position.X == nodo.position.X) && (aux.position.Y == nodo.position.Y))
                 //{
                 //    esta = true;
                 //}

             }
             play.Log.Items.Add("Existen " + listaCerrada.Count + " Nodos en la lista cerrada");
                return esta;
        }

        public static Point[] GetPath(MyAI player, Point posicion, Point objetivo, Tissue mapa)
        {
           
            Point[] fruta;

            List<Nodo> listaAbierta = new List<Nodo>();
            List<Nodo> listaCerrada = new List<Nodo>();

            List<int> G = new List<int>();
            List<int> H = new List<int>();
            List<int> X = new List<int>();
            List<int> Y = new List<int>();

            Nodo actual = new Nodo();
            Nodo aux = new Nodo();
            Nodo nodoMenor = new Nodo();
            int gActual = 0;
            int gAnterior;
            actual.position = posicion;     
            listaCerrada.Add(actual);

            //if (mapa[100, 96].AreaType != PH.Map.AreaEnum.Bone)
            //    player.Log.Items.Add("SOY UN HUESOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");


            //aux.CosteG = 2;
            //aux.CuestaH = 3;
            //aux.CostoF = aux.CosteG + aux.CuestaH;

            //player.Log.Items.Add("DESPUES G: " + aux.CosteG);
            //player.Log.Items.Add("ANTES F: " + aux.CostoF); 

            //while (actual.position != objetivo) 
            for (int k = 0; k < 20; k++)
             {
                 //player.Log.Items.Add("acual: " + new Point(actual.X, actual.Y) + "/" + objetivo);
                for (int i = -1; i <= 1; i++)
                {
                    for (int j = -1; j <= 1; j++)
                    {
                        if ((i != 0) || (j != 0))
                        { 
                            

                            // Este if HORRIBLE sirve para sacar las diagonales.
                            if (((i == 1) && (j == 1)) || ((i == -1) && (j == -1)) || ((i == 1) && (j == -1)) || ((i == -1) && (j == 1))) 
                            {}
                            else
                            {
                               
                                // Asigno el punto a evaluar.
                                aux.position = new Point();
                                aux.position = new Point(actual.position.X + i, actual.position.Y + j);
                                if(contieneNodo(listaCerrada,aux, player)) player.Log.Items.Add("EXISTE");
                                    player.Log.Items.Add("Arranco dnv...");
                                    player.Log.Items.Add("El Nodo auxiliar es  " + aux.position);
                                    //Si el punto es transitable  (NO es hueso)....
                                    if (mapa[aux.position.X, aux.position.Y].AreaType != PH.Map.AreaEnum.Bone)
                                    {
                                        //Calculo el valor H del punto.
                                        aux.CuestaH = Util.Distancia_Manhatan(aux.position, objetivo);

                                        //Si el punto esta en la lista cerrada, no lo evaluo.
                                        //if (listaCerrada.Contains(aux))
                                        //{
                                        //    aux.CuestaH = int.MaxValue;
                                        //}


                                        //Calculo la densidad del punto, para calcular G Actual.
                                        switch (mapa[aux.position.X, aux.position.Y].AreaType)
                                        {
                                            case AreaEnum.LowDensity: gActual = 2;
                                                break;

                                            case AreaEnum.MediumDensity: gActual = 3;
                                                break;

                                            case AreaEnum.HighDensity: gActual = 4;
                                                break;
                                        }

                                        //Si es el punto de salida, no busco los G anteriores
                                        if (actual.position == posicion)
                                        {
                                            aux.CosteG = gActual;
                                        }
                                        //Si no, los busco y lo sumo al G Actual.
                                        else
                                        {
                                            gAnterior = listaCerrada[listaCerrada.Count - 1].CosteG;
                                            aux.CosteG = gAnterior + gActual;
                                        }

                                    }
                                    // Si el punto NO es transitable (es hueso), le asigno un valor de H grande asi pierde
                                    // peso a la hora de evaluar.
                                    else
                                    {
                                        player.Log.Items.Add("la posicion" + aux.position + " es hueso ");
                                        aux.CuestaH = int.MaxValue;
                                        player.Log.Items.Add("el H del supuesto HUESO es...  " + aux.CuestaH);
                                    }


                                    //player.Log.Items.Add("El Nodo actual es " + aux.position);
                                    player.Log.Items.Add("El valor del aux H es : " + aux.CuestaH);
                                    player.Log.Items.Add("El valor de aux G es : " + aux.CosteG);

                                    // Asigno a F como la suma de los 2 costes.
                                    aux.CostoF = Convert.ToUInt32(aux.CuestaH + aux.CosteG);
                                    player.Log.Items.Add("El valor F del aux  es : " + aux.CostoF);

                                    //foreach (Nodo nodo in listaCerrada)
                                    //{
                                    
                                        listaAbierta.Add(aux);
                                    //}
                                    // Agrego el punto a la lista abierta.
                                    

                                    //G.Add(aux.CosteG);
                                    //H.Add(aux.CuestaH);
                                    //X.Add(aux.position.X);
                                    //Y.Add(aux.position.Y);

                                    aux = new Nodo();

                                }
                            
                        }
                    }
                }

                nodoMenor = new Nodo();
                nodoMenor.CostoF = uint.MaxValue;

                foreach (Nodo nodo in listaAbierta)
                {

                    player.Log.Items.Add("Un Nodo de la lista abierta es: " + nodo.position);
                    player.Log.Items.Add("su coste F es: " + nodo.CostoF);
                    player.Log.Items.Add("su coste G es: " + nodo.CosteG);
                    player.Log.Items.Add("su coste H es: " + nodo.CuestaH);

                    if (nodo.CostoF < nodoMenor.CostoF)
                        nodoMenor = nodo;
                }
                if (aux.position != (listaCerrada[listaCerrada.Count - 1].position))
                {
                    player.Log.Items.Add("Hola que tal");
                    listaCerrada.Add(nodoMenor);
                }
              

                listaAbierta.Clear();
                player.Log.Items.Add("El Nodo QUE ELEGI es: " + nodoMenor.position);

                actual = nodoMenor;
                //player.Log.Items.Add("El Nodo actual es " + actual.position);
                //nodoMenor = new Nodo();
           }
            player.Log.Items.Add("--------------------");
            fruta = new Point[listaCerrada.Count];
            int cont = 0;

            foreach (Nodo nodo in listaCerrada)
	        {       
                //player.Log.Items.Add("en lista cerrada: " + nodo.posicion);
                fruta[cont] = nodo.position;
                cont++;
	        }

              
            return fruta;

        }

    }
}
